const PENDING = 'pengding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
  status = PENDING; // 当前promise的状态
  value = undefined; // 当前promise的值
  reason = undefined; // 当前promise如果失败 失败的原因
  successCallbacks = []; // 如果异步 那么将回调存入到对应回调库中
  rejectCallbacks = [];
  // promise 的构造函数接受一个执行器 这个执行器会立即执行
  constructor(executor) {
    // 这个执行器接收两个参数 第一个参数是执行成功 第二个是失败
    // 在执行器执行的过程中如果resolve执行 那么这个promise成功
    try {
      executor(this.resolve, this.reject);
    } catch (error) {
      this.reject(error);
    }
  }
  // 成功调用resolve方法 接收一个参数作为这个promise的返回值存在promise对象中
  resolve = data => {
    // 一旦status状态不是pending 那么就不再执行 保证状态不可逆
    if (this.status !== PENDING) return;
    this.status = FULFILLED;
    this.value = data; // 将promise成功获得的数据存在value中
    // 判断成功回调函数库中是否用未执行的函数 有的话依次执行
    while (this.successCallbacks.length) {
      this.successCallbacks.shift()();
    }
  }
  // 同resolve
  reject = reason => {
    if (this.status !== PENDING) return;
    this.status = REJECTED;
    this.reason = reason;
    while (this.rejectCallbacks.length) this.rejectCallbacks.shift()();
  }
  // then方法 接收两个函数作为参数 第一个是成功的回调
  then = (successCallback, rejectCallback) => {
    successCallback = successCallback || (value => value);
    rejectCallback = rejectCallback || (reason => { throw reason });
    // then方法 返回的是一个新的promise对象 所以在执行then的时候 new一个新的promise
    // 同样的 这个新promise的执行器也会立即执行
    let promise2 = new MyPromise((resolve, reject) => {
      // 当执行到then方法时候 status已经是FULFILLED说明promise已经执行成功
      // 直接执行成功的回调 
      // 同时将成功回调的返回值传递给下一个promise的resolve方法
      setTimeout(() => {
        try {
          if (this.status === FULFILLED) {
            const thenReturnVal = successCallback(this.value);
            resolvePromise(promise2, thenReturnVal, resolve, reject);
          } else if (this.status === REJECTED) {
            const thenReturnVal = rejectCallback(this.reason);
            resolvePromise(promise2, thenReturnVal, resolve, reject);
          } else {
            this.successCallbacks.push(() => {
              try {
                const thenReturnVal = successCallback(this.value);
                resolvePromise(promise2, thenReturnVal, resolve, reject);
              } catch (error) {
                reject(error);
              }
            });
            this.rejectCallbacks.push(() => {
              try {
                const thenReturnVal = rejectCallback(this.reason);
                resolvePromise(promise2, thenReturnVal, resolve, reject);
              } catch (error) {
                reject(error);
              }
            })
          }
        } catch (error) {
          reject(error);
        }
      }, 0);
    });
    return promise2;
  }
}

function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    reject(new TypeError('重复调用自己了哦~'));
  }
  if (x instanceof MyPromise) {
    // 是promise对象 那需要调用Promise的then方法判断这个promise是否成功
    // 如果成功 调用resolve方法 并且把值传递下去 如果失败 调用reject并且把原因传递下去
    x.then(value => resolve(value), reason => reject(reason));
    // x.then(resolve, reject);
  } else {
    resolve(x);
  }
}

const promise33 = new MyPromise((resolve, reject) => {
  resolve('promise33')
})
// (resolve, reject) => {resolve('666')} 是一个执行器函数 会立即执行
// 两个参数分别是promise内部传入的
const promise = new MyPromise((resolve, reject) => {
  // throw new Error('executor error');
  setTimeout(() => {
    reject('失败');
    // resolve(66666);
  }, 2000);
})
promise.then().then().then(value => { console.log(value, '99'); },
  reason => { console.log(reason, '988'); });

// 第一个then调用时 传入两个回调函数
// 第一个then函数内部立刻创建一个新的promise对象 并且then传入的两个函数
// 和then中的所有逻辑代码都作为新promise对象的执行器立即执行
// 如果promise成功 那么执行第一个也就是53行的successCallback
// let p1 = promise.then(data => {
//   // throw new Error('then error');
//   console.log(data);
//   // 这个return会作为successCallback的返回值传入新的promise中
//   // 在新promise调用resolve方法时 可以当做值传递给新promise的value
//   return promise33;
// }, reason => {
//   console.log(reason);
//   return promise33;
// }) // 执行完第一个then后 会返回一个新的promise

// p1.then((thenReturnVal) => { // 再次调用then是调用新promise的then方法
//   // 同时这个新promise的resolve方法接收上一个then方法successCallback的返回值作为value
//   console.log(thenReturnVal, '123');
//   return 'then 3'
// }, (thenRejectVal) => {
//   console.log(thenRejectVal, '122');
// });